// Practically all this code comes from https://github.com/alangrafu/radar-chart-d3
// I only made some additions and aesthetic adjustments to make the chart look better
// (of course, that is only my point of view)
// Such as a better placement of the titles at each line end,
// adding numbers that reflect what each circular level stands for
// Not placing the last level and slight differences in color
//
// For a bit of extra information check the blog about it:
// http://nbremer.blogspot.nl/2013/09/making-d3-radar-chart-look-bit-better.html
import * as d3 from 'd3';
import { DataService } from '../core/data.service';
export class RadarChart {
    constructor(private dataSer: DataService) {}
    draw = (id: any, d: { map: (arg0: (i: any, j: any) => any) => void; }[], options: { [x: string]: any; }) => {
        const cfg = {
            radius: 5,
            w: 200,
            h: 200,
            factor: 1,
            factorLegend: .85,
            levels: 3,
            maxValue: 0,
            radians: 2 * Math.PI,
            opacityArea: 0.3,
            ToRight: 5,
            TranslateX: 80,
            TranslateY: 30,
            ExtraWidthX: 50,
            ExtraWidthY: 50,
            color: d3.scaleOrdinal(d3.schemeCategory10)
        };

        if ('undefined' !== typeof options) {
            for (const i in options) {
                if ('undefined' !== typeof options[i]) {
                    cfg[i] = options[i];
                }
            }
        }
        cfg.maxValue = Math.max(cfg.maxValue, d3.max(d, function (i: { map: (arg0: (o: any) => any) => void; }) {
            return d3.max(i.map(function (o: { value: any; }) { return o.value; })); }));
        let allAxis = [];
        allAxis = d[0].map((i) => i.axis);
        const total = allAxis.length;
        console.log(total, allAxis);
        const radius = cfg.factor * Math.min(cfg.w / 2, cfg.h / 2);
        const Format = d3.format('.1%');
        d3.select(id).select('svg').remove();

        const g = d3.select(id)
            .append('svg')
            .attr('width', cfg.w + cfg.ExtraWidthX)
            .attr('height', cfg.h + cfg.ExtraWidthY)
            .append('g')
            .attr('transform', 'translate(' + cfg.TranslateX + ',' + cfg.TranslateY + ')');
        const tooltip = g.append('text')
            .style('opacity', 0)
            .style('font-family', 'sans-serif')
            .style('font-size', '13px');

        // Circular segments
        for (let j = 0; j < cfg.levels - 1; j++) {
            const levelFactor = cfg.factor * radius * ((j + 1) / cfg.levels);
            g.selectAll('.levels')
                .data(allAxis)
                .enter()
                .append('svg:line')
                // tslint:disable-next-line:no-shadowed-variable
                .attr('x1', function (d: any, i: number) {
                    return levelFactor * (1 - cfg.factor * Math.sin(i * cfg.radians / total)); })
                // tslint:disable-next-line:no-shadowed-variable
                .attr('y1', function (d: any, i: number) {
                    return levelFactor * (1 - cfg.factor * Math.cos(i * cfg.radians / total)); })
                // tslint:disable-next-line:no-shadowed-variable
                .attr('x2', function (d: any, i: number) {
                    return levelFactor * (1 - cfg.factor * Math.sin((i + 1) * cfg.radians / total)); })
                // tslint:disable-next-line:no-shadowed-variable
                .attr('y2', function (d: any, i: number) {
                    return levelFactor * (1 - cfg.factor * Math.cos((i + 1) * cfg.radians / total)); })
                .attr('class', 'line')
                .style('stroke', 'grey')
                .style('stroke-opacity', '0.75')
                .style('stroke-width', '0.3px')
                .attr('transform', 'translate(' + (cfg.w / 2 - levelFactor) + ', ' + (cfg.h / 2 - levelFactor) + ')');
        }

        // Text indicating at what % each level is
        for (let j = 0; j < cfg.levels; j++) {
            const levelFactor = cfg.factor * radius * ((j + 1) / cfg.levels);
            g.selectAll('.levels')
                .data([1]) // dummy data
                .enter()
                .append('svg:text')
                .attr('x', () => levelFactor * (1 - cfg.factor * Math.sin(0)))
                .attr('y', () => levelFactor * (1 - cfg.factor * Math.cos(0)))
                .attr('class', 'legend')
                .style('font-family', 'sans-serif')
                .style('font-size', '10px')
                .attr('transform', 'translate(' + (cfg.w / 2 - levelFactor + cfg.ToRight) + ', ' + (cfg.h / 2 - levelFactor) + ')')
                .attr('fill', '#737373')
                .text(Format((j + 1) * cfg.maxValue / cfg.levels));
        }

        let series = 0;

        const axis = g.selectAll('.axis')
            .data(allAxis)
            .enter()
            .append('g')
            .attr('class', 'axis');

        axis.append('line')
            .attr('x1', cfg.w / 2)
            .attr('y1', cfg.h / 2)
            // tslint:disable-next-line:no-shadowed-variable
            .attr('x2', function (d: any, i: number) { return cfg.w / 2 * (1 - cfg.factor * Math.sin(i * cfg.radians / total)); })
            // tslint:disable-next-line:no-shadowed-variable
            .attr('y2', function (d: any, i: number) { return cfg.h / 2 * (1 - cfg.factor * Math.cos(i * cfg.radians / total)); })
            .attr('class', 'line')
            .style('stroke', 'grey')
            .style('stroke-width', '1px');

        axis.append('text')
            .attr('class', 'legend')
            .text(t => t)
            .style('font-family', 'sans-serif')
            .style('font-size', '11px')
            .attr('text-anchor', 'middle')
            .attr('dy', '1.5em')
            .attr('transform', () => 'translate(0, -5)')
            // tslint:disable-next-line:no-shadowed-variable
            .attr('x', function (d: any, i: number) {
                return cfg.w / 2 * (1 - cfg.factorLegend * Math.sin(i * cfg.radians / total)) - 60 * Math.sin(i * cfg.radians / total); })
            // tslint:disable-next-line:no-shadowed-variable
            .attr('y', function (d: any, i: number) {
                return cfg.h / 2 * (1 - Math.cos(i * cfg.radians / total)) - 20 * Math.cos(i * cfg.radians / total); })
                .on('click', (d) => {
                    console.log(d);
                    this.dataSer.addEnv(d, id);
                });

                const dataValues = [];
        d.forEach(function (y: any, x: any) {
            g.selectAll('.nodes')
                .data(y, function (j: { value: number; }, i: number) {
                    dataValues.push([
                    cfg.w / 2 * (1 - (Math.max(j.value, 0) / cfg.maxValue) * cfg.factor * Math.sin(i * cfg.radians / total)),
                    cfg.h / 2 * (1 - (Math.max(j.value, 0) / cfg.maxValue) * cfg.factor * Math.cos(i * cfg.radians / total))
                    ]);
                });
            dataValues.push(dataValues[0]);
            g.selectAll('.area')
                .data([dataValues])
                .enter()
                .append('polygon')
                .attr('class', 'radar-chart-serie' + series)
                .style('stroke-width', '1px')
                .style('stroke', cfg.color(series))
                // tslint:disable-next-line:no-shadowed-variable
                .attr('points', function (d: string[][]) {
                    let str = '';
                    for (let pti = 0; pti < d.length; pti++) {
                        str = str + d[pti][0] + ',' + d[pti][1] + ' ';
                    }
                    return str;
                })
                .style('fill', function (j: any, i: any) { return cfg.color(series); })
                .style('fill-opacity', cfg.opacityArea)
                .on('mouseover', function () {
                    const z = 'polygon.' + d3.select(this).attr('class');
                    g.selectAll('polygon')
                        .transition(200)
                        .style('fill-opacity', 0.1);
                    g.selectAll(z)
                        .transition(200)
                        .style('fill-opacity', .7);
                })
                .on('mouseout', function () {
                    g.selectAll('polygon')
                        .transition(200)
                        .style('fill-opacity', cfg.opacityArea);
                });
            series++;
        });
        series = 0;


        d.forEach(function (y: any, x: any) {
            g.selectAll('.nodes')
                .data(y).enter()
                .append('svg:circle')
                .attr('class', 'radar-chart-serie' + series)
                .attr('r', cfg.radius / 2)
                .attr('alt', function (j: { value: number; }) { return Math.max(j.value, 0); })
                .attr('cx', function (j: { value: number; }, i: number) {
                    dataValues.push([
                    cfg.w / 2 * (1 - (Math.max(j.value, 0) / cfg.maxValue) * cfg.factor * Math.sin(i * cfg.radians / total)),
                    cfg.h / 2 * (1 - (Math.max(j.value, 0) / cfg.maxValue) * cfg.factor * Math.cos(i * cfg.radians / total))
                    ]);
                    return cfg.w / 2 * (1 - (Math.max(j.value, 0) / cfg.maxValue) * cfg.factor * Math.sin(i * cfg.radians / total));
                })
                .attr('cy', function (j: { value: number; }, i: number) {
                    return cfg.h / 2 * (1 - (Math.max(j.value, 0) / cfg.maxValue) * cfg.factor * Math.cos(i * cfg.radians / total));
                })
                .attr('data-id', function (j: { axis: any; }) { return j.axis; })
                .style('fill', cfg.color(series)).style('fill-opacity', .9)
                .on('mouseover', (d: any) => {
                    const newX = parseFloat(d3.select(this).attr('cx')) - 10;
                    const newY = parseFloat(d3.select(this).attr('cy')) - 5;

                    tooltip
                        .attr('x', newX)
                        .attr('y', newY)
                        .text(Format(d.value))
                        .transition(100)
                        .style('opacity', 1);

                    const z = 'polygon.' + d3.select(this).attr('class');
                    g.selectAll('polygon')
                        .transition(100)
                        .style('fill-opacity', 0.1);
                    g.selectAll(z)
                        .transition(100)
                        .style('fill-opacity', .7);
                })
                .on('mouseout', function () {
                    tooltip
                        .transition(100)
                        .style('opacity', 0);
                    g.selectAll('polygon')
                        .transition(100)
                        .style('fill-opacity', cfg.opacityArea);
                })
                .append('svg:title')
                .text(function (j: { value: number; }) { return Math.max(j.value, 0); });

            series++;
        });
        // Tooltip
        // tooltip = g.append('text')
        //     .style('opacity', 0)
        //     .style('font-family', 'sans-serif')
        //     .style('font-size', '13px');
    }
}
